import {
  env
} from '../env.config'

import {
  getUserInfo
} from './util.js'

function isObject(obj) {
  return Object.prototype.toString.call(obj) === '[object Object]';
}

function forEach(obj, fn) {
  for (var key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      fn(obj[key], key);
    }
  }
}
// 对象合并 === 如果你的工具库中已有该方法的实现，可以将其替换 ===
export function merge() {
  var result = {};

  function assignValue(val, key) {
    if (isObject(result[key]) && isObject(val)) {
      result[key] = merge(result[key], val);
    } else {
      result[key] = val;
    }
  }
  for (var i = 0, l = arguments.length; i < l; i++) {
    forEach(arguments[i], assignValue);
  }
  return result;
}
// http规则校验
function urlRegExp(value) {
  return /http(s)?:\/\/([\w-]+\.)+[\w-]+(\/[\w-.\/?%&=]*)?/.test(value)
}

class Http {
  constructor(config = {}) {
    this.config = merge({}, {
      baseUrl: '', // 请求的根域名
      header: {}, // 默认的请求头
      method: 'POST',
      dataType: 'json',
      responseType: 'text', // 此参数无需处理，因为5+和支付宝小程序不支持，默认为text即可
      loading: true, // 默认请求是否开启loading
    }, config)
    // 拦截器
    this.interceptor = {
      // 请求前的拦截
      request: null,
      // 请求后的拦截
      response: null
    }
  }

  // 主要请求部分
  async request(options = {}) {
    if (options.loading === undefined) options.loading = this.config.loading
    // 检查请求拦截
    if (this.interceptor.request && typeof this.interceptor.request === 'function') {
      let tmpConfig = {};
      let interceptorRequest = this.interceptor.request(options);
      if (interceptorRequest === false) {
        // 返回一个处于pending状态中的Promise，来取消原promise，避免进入then()回调
        return new Promise(() => {});
      }
      this.options = interceptorRequest;
    }
    options.dataType = options.dataType || this.config.dataType;
    options.responseType = options.responseType || this.config.responseType;
    options.url = options.url || '';
    options.params = options.params || {};
    options.header = merge({}, this.config.header, options.header);
    options.method = options.method || this.config.method;

    let token = wx.getStorageSync('token')
    let that = this
    if (!token) {
      try {
        let wxLogin
        if (!wx.getStorageSync('environment')) {
          wxLogin = await wx.login()
        } else {
          wxLogin = await qyLogin()
        }
        if (wxLogin.code) {
          let mySelfLogin = await that.req({
            method: 'POST',
            url: env.APP_BASE_URL + `/user/${env.login}`,
            data: {
              code: wxLogin.code,
              type: wx.getStorageSync('environment') ? '2' : '1'
            }
          })
          if (mySelfLogin) {
            wx.setStorage({
              key: 'token',
              data: mySelfLogin
            })
            options.header.Authorization = mySelfLogin
            return that.req(options)
          }
        }
      } catch (error) {
        console.log(error)
        wx.showToast({
          title: `${error.errMsg=='login:fail Failed to fetch'?'登录失败，请重新进入':'未知错误，请重新进入'}`,
          icon: "none"
        })
      }
    } else {
      return this.req(options)
    }
  }
  req(options) {
    let requestTask = {}
    return new Promise((resolve, reject) => {
      options.complete = (response) => {
        response.loading = options.loading
        // 判断是否存在拦截器
        if (this.interceptor.response && typeof this.interceptor.response === 'function') {
          let resInterceptors = this.interceptor.response(response);
          // 如果拦截器不返回false，直接接入then回调
          if (resInterceptors !== false) {
            resolve(resInterceptors);
          } else {
            // 如果拦截器返回false，意味着拦截器定义者认为返回有问题，直接接入catch回调
            reject(response.data || response);
          }
        } else {
          // 如果要求返回原始数据，就算没有拦截器，也返回最原始的数据
          resolve(response);
        }
      }
      // 判断用户传递的URL是否/开头,如果不是,加上/，
      options.url = urlRegExp(options.url) ? options.url : (this.config.baseUrl + options.url);

      // 发送请求
      if (options.method == 'FILE') {
        requestTask = wx.uploadFile(options);
      } else {
        requestTask = wx.request(options);
      }
      if (options.setCancelToken) options.setCancelToken(requestTask)
    })
  }
}

function qyLogin() {
  return new Promise((resolve, reject) => {
    wx.qy.login({
      success: (r) => {
        resolve(r)
      },
      fail: (e) => {
        reject(e)
      }
    })
  })
}

export default Http